package com.tengju.user.application.login;

import com.tengju.user.application.shared.ApplicationException;
import com.tengju.user.application.shared.ApplicationExceptionCode;
import com.tengju.user.domain.model.login.LoginForm;
import com.tengju.user.domain.model.login.LoginResult;
import com.tengju.user.domain.model.login.UserAccount;
import com.tengju.user.domain.model.login.UserType;
import com.tengju.user.domain.model.sms.OperationType;
import com.tengju.user.domain.model.user.*;
import com.tengju.user.domain.service.RemoteUserService;
import com.tengju.user.domain.shared.DomainException;
import com.tengju.user.domain.shared.DomainExceptionCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Random;

/**
 * @author wuziyang
 */
@Slf4j
@Service("mobileCodeLoginService")
public class MobileCodeLoginStrategyImpl implements LoginStrategy {


    @Value("${user.headImage.default}")
    String env;

    @Value("${user.headImage.default}")
    String defaultHeadImage;

    private SmsVerifyCodeService smsVerifyCodeService;
    private RemoteUserService remoteUserService;
    private UserInfoRepository userInfoRepository;
    private UserAccountRepository userAccountRepository;
    private UserStaffRepository userStaffRepository;
    private AbmUserInfoRepository abmUserInfoRepository;

    @Autowired
    public MobileCodeLoginStrategyImpl(SmsVerifyCodeService smsVerifyCodeService, RemoteUserService remoteUserService, UserInfoRepository userInfoRepository, UserAccountRepository userAccountRepository, UserStaffRepository userStaffRepository, AbmUserInfoRepository abmUserInfoRepository) {
        this.smsVerifyCodeService = smsVerifyCodeService;
        this.remoteUserService = remoteUserService;
        this.userInfoRepository = userInfoRepository;
        this.userAccountRepository = userAccountRepository;
        this.userStaffRepository = userStaffRepository;
        this.abmUserInfoRepository = abmUserInfoRepository;
    }

    @Override
    public LoginResult login(LoginForm loginForm, UserAccount userAccount) {

        boolean checkCodeResult = smsVerifyCodeService.checkVerifyCode(loginForm.getUserType(),
                OperationType.LOGIN, loginForm.getAreaCode(),
                loginForm.getUsername(), loginForm.getVerificationCode());

        if (!checkCodeResult) {
            return null;
        }

        //账户存在 进行登陆
        if (userAccount != null) {

            //更新上次登陆ip及上次登陆时间
            userAccount.login(loginForm.getLoginIp());
            boolean loginResult = userAccountRepository.login(userAccount);

            if (!loginResult) {
                return null;
            }

            LoginDesc loginDesc;

            if (loginForm.getUserType() == UserType.USER) {
                loginDesc = userInfoRepository.getByUserId(userAccount.getUserId());
            } else if (loginForm.getUserType() == UserType.STAFF) {
                loginDesc = userStaffRepository.queryUserStaff(userAccount.getStaffId());
            } else {
                log.error("userType error,mobile:{}",loginForm.getUsername());
                throw ApplicationException.error(ApplicationExceptionCode.INVALID_DATA,"用户类型异常");
            }

            return new LoginResult(loginDesc.getId(),
                    userAccount.getUsername(),
                    loginDesc.getNickName(),
                    loginDesc.getHeadImage(),
                    null,
                    loginDesc.getUserType(),
                    loginDesc.getUserIdCode(),
                    new ArrayList<>(),
                    new ArrayList<>(),
                    userAccount.getPassword(),
                    new ArrayList<>(),
                    null);
        } else {
            return null;
        }
    }

    @Override
    public LoginResult registerAndLogin(LoginForm loginForm) {

        if (UserType.STAFF == loginForm.getUserType()) {
            throw DomainException.error(DomainExceptionCode.NOT_REGIST_ERROR);
        }

        //关联经销商
        UserInfo userInfo= remoteUserService.getByMobile(loginForm.getAreaCode(),loginForm.getUsername());


        UserId userId;
        UserAccount userAccount;

        if (userInfo == null) {
            //创建普通用户
            userInfo = initNormalUser(loginForm);
            userId = userInfoRepository.store(userInfo);

            userAccount = initNormalUserAccount(loginForm, userId.getValue(),DigestUtils.md5DigestAsHex(randomPwd(16).getBytes()));
            userAccountRepository.store(userAccount);
        } else {
            //兼容星级项目
            UserInfo existUser = userInfoRepository.getByIdCode(userInfo.getIdCode());
            if (existUser != null) {
                UserAccount account = userAccountRepository.queryUserAccount(loginForm.getUserType(), existUser.getUserId());
                if (account != null) {
                    log.error("user account error,mobile:{}",loginForm.getUsername());
                    throw ApplicationException.error(ApplicationExceptionCode.LOGIN_FAIL);
                }
                userInfoRepository.updateUserInfo(userInfo);
                userId = existUser.getUserId();
            } else {
                userId = userInfoRepository.store(userInfo);
            }

            String password = abmUserInfoRepository.getPassword(userInfo.getIdCode());
            if (StringUtils.isEmpty(password)) {
                password = DigestUtils.md5DigestAsHex(randomPwd(16).getBytes());
            }

            userAccount = initNormalUserAccount(loginForm, userId.getValue(),password);
            userAccountRepository.store(userAccount);
        }


        return new LoginResult(userId.getValue(),
                userAccount.getUsername(),
                userInfo.getNickName(),
                userInfo.getHeadImage(),
                null,
                UserType.USER,
                userInfo.getIdCode(),
                new ArrayList<>(),
                new ArrayList<>(),
                userAccount.getPassword(),
                new ArrayList<>(),
                null);

    }

    private UserAccount initNormalUserAccount(LoginForm loginForm, long outId, String password) {

        UserId userId = null;
        StaffId staffId = null;

        if (loginForm.getUserType() == UserType.USER) {
            userId = new UserId(outId);
        } else if (loginForm.getUserType() == UserType.STAFF) {
            staffId = new StaffId(outId);
        } else {
            throw DomainException.error(DomainExceptionCode.INVALID_DATA,"用户类型错误");
        }

        return new UserAccount(null,
                loginForm.getAreaCode() + loginForm.getUsername(),
                password, loginForm.getUserType(),
                userId,staffId,loginForm.getLoginIp(),loginForm.getLoginTime(),0L);
    }

    private UserInfo initNormalUser(LoginForm loginInfo) {
        return new UserInfo(loginInfo.getAreaCode(),
                loginInfo.getUsername(),
                loginInfo.getUsername(),
                0,0,Sex.UNKNOW,defaultHeadImage);
    }

    private String randomPwd(int length){
        String str="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*";
        Random random=new Random();
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<length;i++){
            int number=random.nextInt(70);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }
}
